﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Coolite.Ext.Web;
using Newtonsoft.Json.Linq;
using Pap.Core.Utilities;
using Pap.Data;
using Pap.Web.Modules.Loan.ViewModel;
using Pap.Web.Utils;
using Utils.UIPermission;

namespace Pap.Web.Modules.Loan.Views
{
    /// <summary>
    /// 
    /// </summary>
    public partial class CreateBoard : BasePage<CreateBoardViewModel>, IPermittedPage
    {
        #region Viewstate Properties

        /// <summary>
        /// Gets or sets the board members.
        /// </summary>
        /// <value>
        /// The board members.
        /// </value>
        private List<IBoardMember> BoardMembers
        {
            get { return (List<IBoardMember>)Session["selectedMembers"]; }
            set { Session.Add("selectedMembers", value); }
        }

        /// <summary>
        /// Gets or sets all users.
        /// </summary>
        /// <value>
        /// All users.
        /// </value>
        private List<IBoardMember> AllUsers
        {
            get { return (List<IBoardMember>)Session["allUsers"]; }
            set { Session.Add("allUsers", value); }
        }

        #endregion

        #region QueryString

        /// <summary>
        /// Gets the board id.
        /// </summary>
        private string BoardId
        {
            get { return Request.QueryString["BoardID"]; }
        }

        #endregion

        #region Event Handlers

        /// <summary>
        /// Handles the Load event of the Page control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                if (!Ext.IsAjaxRequest)
                {
                    AllUsers = ViewModel.GetAllMembers().ToList();

                    if (!BoardId.IsNullOrEmpty())
                    {
                        BoardMembers = new List<IBoardMember>();
                        IBoard editBoard = ViewModel.GetLoan(BoardId.ToGuid());
                        IEnumerable<IBoardMember> editBoardMembers = from member in editBoard.BoardMembers
                                                                     select member;

                        dateHoldDate.Value = editBoard.BoardDate;
                        BoardMembers.AddRange(editBoardMembers);
                        AllUsers.RemoveAll(
                            displayuser => editBoardMembers.Select(user => user.BoardMemberID).Contains(displayuser.BoardMemberID));

                        IEnumerable editBoardLoans = ViewModel.GetUnAssignedLoansByBoardId(editBoard.BoardID);

                        if (editBoard.BoardLoans.Count() > 0)
                        {
                            cmbProjects.SelectedItem.Value =
                                editBoard.BoardLoans.First().LoanObj.ProjectStage.ProjectID.ToString();
                        }
                        storeLoans.DataSource = editBoardLoans;
                        storeLoans.DataBind();

                        var selection = gridWaitingLoans.SelectionModel.Primary as RowSelectionModel;
                        IEnumerable<SelectedRow> selectedRows = (from loan in editBoard.BoardLoans
                                                                 select new SelectedRow
                                                                            {
                                                                                RecordID = loan.LoanID.ToString()
                                                                            });
                        if (selection != null)
                        {
                            selection.SelectedRows.AddRange(selectedRows);
                            selection.UpdateSelection();
                        }
                    }
                    else
                    {
                        BoardMembers = new List<IBoardMember>();
                    }

                    dateHoldDate.MinDate = DateTime.Today;

                    storeResults.DataSource = AllUsers;
                    storeResults.DataBind();

                    storeMembers.DataSource = BoardMembers;
                    storeMembers.DataBind();

                    storeProjects.DataSource = ViewModel.GetCurrentUserProjects(RegistryInfo.UserID);
                    storeProjects.DataBind();

                    //if (cmbProjects.Items.Count == 1)
                    //{
                    //    cmbProjects.SelectedIndex = 0;
                    //    cmbProjects.ReadOnly = true;
                    //    cmbProjects.Disabled = true;
                    //}

                    //CmbProjects_Selected(null, null);
                }
            }
        }

        /// <summary>
        /// Handles the Selected event of the CmbProjects control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="args">The <see cref="Coolite.Ext.Web.AjaxEventArgs"/> instance containing the event data.</param>
        protected void CmbProjects_Selected(object sender, AjaxEventArgs args)
        {
            if (!BoardId.IsNullOrEmpty())
            {
                IBoard editBoard = ViewModel.GetLoan(BoardId.ToGuid());
                if (editBoard != null && editBoard.BoardLoans.Count() > 0)
                {
                    if (editBoard.BoardLoans.First().LoanObj.ProjectStage.ProjectID == cmbProjects.SelectedItem.Value.ToGuid())
                    {
                        UpdateBankAccountValue();
                        return;
                    }
                }
            }

            var loans = ViewModel.GetUnAssignedLoans(cmbProjects.SelectedItem.Value.ToGuid());
            storeLoans.DataSource = loans;
            storeLoans.DataBind();

            // cannot use for, using foreach with index
            var index = 0;
            foreach (var loan in loans)
            {
                if (loan.GetProperty<bool>("Selected"))
                {
                    checkSelectionModel.SelectedRows.Add(new SelectedRow(index));
                }
                index++;
            }

            UpdateBankAccountValue();
        }

        private void UpdateBankAccountValue()
        {
            txtbankAccountAndDues.Text =
                ViewModel.GetCommitteeBanlkAccountPlusDues(cmbProjects.SelectedItem.Value.ToGuid(),
                                                           Convert.ToDateTime(dateHoldDate.Value)).ToString();
        }

        /// <summary>
        /// Handles the Selected event of the DateHoldDate control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="args">The <see cref="Coolite.Ext.Web.AjaxEventArgs"/> instance containing the event data.</param>
        protected void DateHoldDate_Selected(object sender, AjaxEventArgs args)
        {
            if (!cmbProjects.SelectedItem.Value.IsNullOrEmpty())
            {
                txtbankAccountAndDues.Text =
                    ViewModel.GetCommitteeBanlkAccountPlusDues(cmbProjects.SelectedItem.Value.ToGuid(),
                                                               Convert.ToDateTime(dateHoldDate.Value)).ToString();
            }
        }

        /// <summary>
        /// Handles the Command event of the gridMembers control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="args">The <see cref="Coolite.Ext.Web.AjaxEventArgs"/> instance containing the event data.</param>
        protected void gridMembers_Command(object sender, AjaxEventArgs args)
        {
            var userId = args.ExtraParams["UserId"] ?? "";
            var displayName = args.ExtraParams["DisplayName"] ?? "";
            if (userId.ToGuid() == Guid.Empty)
                return;

            switch (args.ExtraParams["CommandName"])
            {
                case "AddMember":
                    AddToBoard(new BoardMember { BoardMemberID = userId.ToGuid(), BoardMemberName = displayName });
                    break;
                case "RemoveMember":
                    RemoveFromBoard(new BoardMember { BoardMemberID = userId.ToGuid(), BoardMemberName = displayName });
                    break;
                default:
                    return;
            }
        }

        /// <summary>
        /// Handles the Clicked event of the btnBack control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="args">The <see cref="Coolite.Ext.Web.AjaxEventArgs"/> instance containing the event data.</param>
        protected void btnBack_Clicked(object sender, AjaxEventArgs args)
        {
            this.RedirectToPreviousPage();
        }

        /// <summary>
        /// Handles the Clicked event of the btnSubmit control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="args">The <see cref="Coolite.Ext.Web.AjaxEventArgs"/> instance containing the event data.</param>
        protected void btnSubmit_Clicked(object sender, AjaxEventArgs args)
        {
            if (args.ExtraParams["WaitingLoansGrid"] != null)
            {
                var sm = gridWaitingLoans.SelectionModel.Primary as RowSelectionModel;
                var boardDate = (DateTime)dateHoldDate.Value;
                if (ViewModel.ValidBordDate(boardDate, BoardId.ToGuid()))
                {
                    IEnumerable<Guid> selectedloanIDs = from row in sm.SelectedRows
                                                        select row.RecordID.ToGuid();

                    var errorsLoansNumbers = new List<int>();

                    var json = JSON.Deserialize(args.ExtraParams["WaitingLoansGrid"]) as JArray;

                    var lastLoanNumber =
                        json.SingleOrDefault(
                            jt => jt["LoanID"].ToString().Trim('"').ToGuid() == selectedloanIDs.LastOrDefault())[
                                "LoanNumber"].ToString().Trim('"').ToInt32();

                    var loansData = new Dictionary<Guid, string>();
                    var savedLoansData = new Dictionary<Guid, string>();

                    for (int i = 0; i < json.Count; i++)
                    {
                        if (!selectedloanIDs.Contains(json[i]["LoanID"].ToString().Trim('"').ToGuid()))
                        {
                            if (json[i]["LoanNumber"].ToString().Trim('"').ToInt32() < lastLoanNumber
                                && json[i]["Notes"].ToString().Trim('"').IsNullOrEmpty())
                            {
                                errorsLoansNumbers.Add(json[i]["LoanNumber"].ToString().Trim('"').ToInt32());
                            }
                            else
                            {
                                string tempString = "";
                                if (json[i]["Notes"] != null)
                                    tempString = (json[i]["Notes"].ToString().Trim('"'));
                                savedLoansData.Add(json[i]["LoanID"].ToString().Trim('"').ToGuid(), tempString);
                            }
                        }
                        else
                        {
                            string tempString = "";
                            if (json[i]["Notes"] != null)
                                tempString = (json[i]["Notes"].ToString().Trim('"'));
                            loansData.Add(json[i]["LoanID"].ToString().Trim('"').ToGuid(), tempString);
                        }
                    }

                    if (errorsLoansNumbers.Count > 0)
                    {
                        string[] loansNumbers = Array.ConvertAll(errorsLoansNumbers.ToArray(), Convert.ToString);
                        string errorloans = String.Join(", ", loansNumbers);

                        Ext.Msg.Configure(new MessageBox.Config
                                              {
                                                  Title = GetLocalResourceObject("MBError").ToString(),
                                                  Message = GetLocalResourceObject("MBErrorLoans") + " " + errorloans,
                                                  Buttons = MessageBox.Button.OK,
                                                  Icon = MessageBox.Icon.ERROR
                                              }).Show();
                    }
                    else
                    {
                        ViewModel.CreateBoard(RegistryInfo.CommitteeID, boardDate, BoardMembers.ToArray(), loansData,
                                              BoardId);
                        this.RedirectFromThisPage("CreateBoard", new string[0]);
                    }
                }
                else
                {
                    dateHoldDate.MarkInvalid(GetLocalResourceObject("BoardMonthLimit").ToString());
                }
            }
        }

        /// <summary>
        /// Handles the Clicked event of the BtnSave control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="Coolite.Ext.Web.AjaxEventArgs"/> instance containing the event data.</param>
        protected void BtnSave_Clicked(object sender, AjaxEventArgs e)
        {
            var boardDate = (DateTime)dateHoldDate.Value; // BoardID != null ? BoardID.ToGuid() : new Nullable<Guid>()

            if (ViewModel.ValidBordDate(boardDate, BoardId.ToGuid()))
            {
                var json = JSON.Deserialize(e.ExtraParams["WaitingLoansGrid"]) as JArray;
                var sm = gridWaitingLoans.SelectionModel.Primary as RowSelectionModel;

                IEnumerable<Guid> SelectedloanIDs = from row in sm.SelectedRows
                                                    select row.RecordID.ToGuid();

                var LoansData = new Dictionary<Guid, string>();

                for (int i = 0; i < json.Count; i++)
                {
                    if (SelectedloanIDs.Contains(json[i]["LoanID"].ToString().Trim('"').ToGuid()))
                    {
                        LoansData.Add(json[i]["LoanID"].ToString().Trim('"').ToGuid(),
                                      json[i]["Notes"].ToString().Trim('"'));
                    }
                }

                ViewModel.SaveBoard(RegistryInfo.CommitteeID, boardDate, BoardMembers.ToArray(), LoansData, BoardId);
                this.RedirectToPreviousPage();
            }
            else
            {
                dateHoldDate.MarkInvalid(GetLocalResourceObject("BoardMonthLimit").ToString());
            }
        }

        /// <summary>
        /// Handles the Clicked event of the BtnPrint control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="Coolite.Ext.Web.AjaxEventArgs"/> instance containing the event data.</param>
        protected void BtnPrint_Clicked(object sender, AjaxEventArgs e)
        {
            if (e.ExtraParams["WaitingLoansGrid"] != null)
            {
                var json = JSON.Deserialize(e.ExtraParams["WaitingLoansGrid"]) as JArray;


                IEnumerable boardMembersPrint = ViewModel.GetMemberObjects(BoardMembers);
                object boardloansPrint = GetPrintBoardLoansView(json);

                Session["boardMomMembersPrint"] = boardMembersPrint;
                Session["boardMomloansPrint"] = boardloansPrint;

                int boardNum = ViewModel.GetNewBoardCommitteeNumber();

                wndBoardPrint.LoadContent("~/Loan.route/PrintBoardMom?BoardNumber=" + boardNum);
                wndBoardPrint.Show();
            }
        }

        /// <summary>
        /// Handles the Click event of the gridBoardMembers control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected void gridBoardMembers_Click(object sender, EventArgs e)
        {
            wndSelectMember.Show();
        }

        //this event isn't called 

        /// <summary>
        /// Handles the Closed event of the wndBoardPrintPrint control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="Coolite.Ext.Web.AjaxEventArgs"/> instance containing the event data.</param>
        protected void wndBoardPrintPrint_Closed(object sender, AjaxEventArgs e)
        {
            if (Session["boardMembersPrint"] != null)
            {
                Session.Remove("boardMembersPrint");
            }
        }

        #endregion

        #region Private Functions

        /// <summary>
        /// Removes from board.
        /// </summary>
        /// <param name="member">The member.</param>
        private void RemoveFromBoard(BoardMember member)
        {
            int count = BoardMembers.RemoveAll(d => d.BoardMemberID == member.BoardMemberID);
            if (count > 0)
            {
                storeMembers.DataSource = BoardMembers;
                storeMembers.DataBind();
                AllUsers.Add(new BoardMember { BoardMemberID = member.BoardMemberID, BoardMemberName = member.BoardMemberName });
                storeResults.DataSource = AllUsers;
                storeResults.DataBind();
            }
        }

        /// <summary>
        /// Adds to board.
        /// </summary>
        /// <param name="member">The member.</param>
        private void AddToBoard(BoardMember member)
        {
            if (BoardMembers.Count(u => u.BoardMemberID == member.BoardMemberID) == 0)
            {
                BoardMembers.Add(new BoardMember { BoardMemberID = member.BoardMemberID, BoardMemberName = member.BoardMemberName });
                storeMembers.DataSource = BoardMembers;
                storeMembers.DataBind();
                AllUsers.RemoveAll(u => u.BoardMemberID == member.BoardMemberID);
                storeResults.DataSource = AllUsers;
                storeResults.DataBind();
            }
        }

        /// <summary>
        /// Gets the board loans view.
        /// </summary>
        /// <param name="json">The json.</param>
        /// <returns></returns>
        private object GetBoardLoansView(JArray json)
        {
            return (from item in json
                    select new
                               {
                                   LoanNumber = item["LoanNumber"].ToString().Trim('"'),
                                   CustomerName = item["CustomerName"].ToString().Trim('"'),
                                   ProjectName = item["LoanType"].ToString().Trim('"'),
                                   RequestedAmount = item["RequestedAmount"].ToString().Trim('"'),
                                   ResponsibleAmount = item["ResponsibleProposedAmount"].ToString().Trim('"'),
                                   RequestedPeriod = item["RequestedPaymentPeriod"].ToString().Trim('"'),
                                   Notes = item["Notes"].ToString().Trim('"')
                               });
        }

        /// <summary>
        /// Gets the print board loans view.
        /// </summary>
        /// <param name="json">The json.</param>
        /// <returns></returns>
        private object GetPrintBoardLoansView(JArray json)
        {
            return (from item in json
                    select new
                               {
                                   LoanNumber = item["LoanNumber"].ToString().Trim('"'),
                                   CustomerName = item["CustomerName"].ToString().Trim('"'),
                                   LoanType = item["LoanType"].ToString().Trim('"'),
                                   LoanAmount = item["RequestedAmount"].ToString().Trim('"'),
                                   BoardLoanAmount = string.Empty,
                                   Decision = string.Empty,
                                   Notes = item["Notes"].ToString().Trim('"')
                               });
        }

        #endregion

        #region IPermittedPage Members

        /// <summary>
        /// Gets the name of the permission.
        /// </summary>
        /// <value>
        /// The name of the permission.
        /// </value>
        public string PermissionName
        {
            get { return "CreateBoard"; }
        }

        #endregion
    }
}